#include"tcp.h" 

int socketInit(){
    int listenfd = socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(listenfd,-1,"socket");
    return listenfd; 
}

void setNonblock(int fd){
    int flags = fcntl(fd,F_GETFL);
    flags |=O_NONBLOCK;
    fcntl(fd,F_SETFL,flags);
}

struct sockaddr_in inetaddress(const char*ip, uint16_t port){
    struct sockaddr_in serveraddr;
    memset(&serveraddr,0,sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;//进行ipv4通信
    serveraddr.sin_port = htons(port);//将端口转化为网络字节序
    serveraddr.sin_addr.s_addr = inet_addr(ip);//将ip的点分十进制转化为网络字节序
    return serveraddr;
}

int tcpServerInit(const char*ip, uint16_t port){
    int ret;
    //创建套接字
    int listenfd = socketInit();

    int reuse = 1;
    if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
        perror("setsockopt");
    }

    //绑定网络地址
    struct sockaddr_in serveraddr = inetaddress(ip, port);
    ret = bind(listenfd,
               (struct sockaddr*)&serveraddr,
               sizeof(serveraddr));
    ERROR_CHECK(ret,-1,"bind");

    //进行监听
    ret = listen(listenfd,100);
    ERROR_CHECK(ret,-1,"listen");
    printf("listen has complete\n");
    return listenfd;
}

int sendn(int fd,const void* p,int len){
    int left = len;
    char * pbuf = (char*)p;
    int ret = 0;
    while(left > 0){
        ret = send(fd,pbuf,len,0);
        if(ret < 0 ){
            perror("send");
            break;
        }else{
            pbuf+=ret;
            left-=ret;
        }
    }
    return len-left;//返回发送了多长的数据
}

int recvn(int sfd, void *p, int len)
{
    char *str = (char *)p;
    int cur = 0, left = len, ret;
    while (left > 0)
    {
        ret = recv(sfd, str + cur, left, 0);
        ERROR_CHECK(ret, -1, "recv");
        cur += ret;
        left -= ret;

    }
    return cur;

}

//通道层初始化
void channelIsInit(channel_t* p, int length){
    for(int i=0;i<length;i++){
        channelInit(p+i);
    }
}

void channelInit(channel_t* p){
    if(p){
        p->sockfd = -1;//未使用
        p->recvbufSize = 0;
        p->sendbufSize = 0;
        memset(p->recvbuf,0,BUFSIZE);
        memset(p->sendbuf,0,BUFSIZE);
    }
}

void channelDestory(channel_t*p){
    if(p){
        close(p->sockfd);
        channelInit(p);
    }
}

void channelAdd(channel_t* p,int length,int fd){
    for(int i=0;i<length;i++){
        if(p[i].sockfd == -1){
            p[i].sockfd = fd;
            clearRecvbuf(p);
            clearSendbuf(p);
            break;
        }
    }
}

void channelDel(channel_t* p,int length,int fd){
    int idx = channelGetIndex(p,length,fd); 
    if(idx != -1){
        channelDestory(p+idx);
    }
}

int channelGetIndex(channel_t* p,int length,int fd){
    if(p){
        for(int i=0;i<length;i++){
            if(p[i].sockfd==fd){
                return i;
            }
        }
        return -1;//没找到
    }
}

void clearRecvbuf(channel_t* p){
    if(p){
        p->recvbufSize = 0;
        memset(p->recvbuf,0,BUFSIZE);
    }
}
void clearSendbuf(channel_t* p){
    if(p){
        p->sendbufSize = 0;
        memset(p->sendbuf,0,BUFSIZE);
    }
}

//epoll

int epollCreat(){
    int fd = epoll_create1(0);
    ERROR_CHECK(fd,-1,"epoll_create1");
    return fd;
}
//增加读写事件
void epollAddReadWriteEvent(int epfd,int fd){
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN | EPOLLOUT;
    if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&evt)<0){
        perror("epoll_ctl");
    }
}

//增加写事件
void epollAddReadEvent(int epfd,int fd){
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN;
    if(epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&evt)<0){
        perror("epoll_ctl");
    }
}

//初始情况下监听的是读写事件
//现在希望他只监听读事件
void epollClearWriteEvent(int epfd,int fd){
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN;
    if(epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&evt)<0){
        perror("epoll_ctl");
    }
}

//初始情况下监听的是读事件
//现在希望他监听读和写事件
void epollSetWriteEvent(int epfd,int fd){
    struct epoll_event evt;
    evt.data.fd = fd;
    evt.events = EPOLLIN | EPOLLOUT;
    if(epoll_ctl(epfd,EPOLL_CTL_MOD,fd,&evt)<0){
        perror("epoll_ctl");
    }
}

//删除监听的事件
void epollDelEvent(int epfd,int fd){
    struct epoll_event evt;
    evt.data.fd = fd;
    if(epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&evt)<0){
        perror("epoll_ctl");
    }
}
